2.3 Numpy 数组的计算:通用函数

本文源码请见我的GitHub

2.3 Numpy 数组的计算:通用函数

numpy数组计算有时候会很慢,使之边块的关键是利用向量化操作,通常在通用函数(ufunc)中实现。

2.3.1 缓慢的循环

Python在每次循环首先检查对象的类型,并且动态查找可以使用该数据类型的正确函数。Cpython在每次循环时必须做数据类型的检查和函数的调度。如果在编译代码是进行这样操作,就能在代码执行前知晓类型的生命,结果的计算也会更加有效率。

2.3.3 探索Numpy的通用函数

一般有两种存在形式:一元通用函数,对单个输入操作;二元通用函数

1.数组的运算

标准的加减乘除都可以使用

1
import numpy as np
1
2
3
4
5
6
7
x = np.arange(4)
print("x =",x)
print("x + 5 =", x + 5)
print("x - 5 =", x - 5)
print("x * 2 =", x * 2)
print("X / 2 = ",x / 2)
print("x // 2 = ",x // 2)#地板除法
x   = [0 1 2 3]
x + 5  = [5 6 7 8]
x - 5  = [-5 -4 -3 -2]
x *  2  = [0 2 4 6]
X / 2  =  [0.  0.5 1.  1.5]
x // 2 =  [0 0 1 1]
1
#逻辑非、 **表示的指数运算符和%表示的模运算符的一元通用函数:
1
2
3
print("-x    =", -x)
print("x ** 2 =",x**2)
print("x % 2 = ",x % 2)
-x    = [ 0 -1 -2 -3]
x ** 2 = [0 1 4 9]
x % 2 =  [0 1 0 1]

所有这些运算符都是Numpy内置函数的简单封装器

2.绝对值

1
2
x  = np.array([1,-22,3,-4])
abs(x)
array([ 1, 22,  3,  4])
1
np.absolute(x)
array([ 1, 22,  3,  4])

这个函数也可以处理复数。 绝对值返回的是该复数的幅度:

1
2
x = np.array([3 - 4j, 4-3j,6 + 8j])
abs(x)#其实就是模
array([ 5.,  5., 10.])

3.三角函数

1
theta = np.linspace(0, np.pi, 3)
1
2
3
4
print("theta  = ",theta)
print("sin(theta) = ", np.sin(theta))
print("cos(theta) = ",np.cos(theta))
print("tan(theta) = ",np.tan(theta))
theta  =  [0.         1.57079633 3.14159265]
sin(theta) =  [0.0000000e+00 1.0000000e+00 1.2246468e-16]
cos(theta) =  [ 1.000000e+00  6.123234e-17 -1.000000e+00]
tan(theta) =  [ 0.00000000e+00  1.63312394e+16 -1.22464680e-16]

逆三角函数也是可以用的

1
2
3
4
print("theta  = ",theta)
print("arcsin(theta) = ", np.arcsin(theta))
print("arccos(theta) = ",np.arccos(theta))
print("arctan(theta) = ",np.arctan(theta))
theta  =  [0.         1.57079633 3.14159265]
arcsin(theta) =  [ 0. nan nan]
arccos(theta) =  [1.57079633        nan        nan]
arctan(theta) =  [0.         1.00388482 1.26262726]


D:\Software\Anaconda3\lib\site-packages\ipykernel_launcher.py:2: RuntimeWarning: invalid value encountered in arcsin

D:\Software\Anaconda3\lib\site-packages\ipykernel_launcher.py:3: RuntimeWarning: invalid value encountered in arccos
  This is separate from the ipykernel package so we can avoid doing imports until

4.指数和对数

1
2
3
4
5
x = [1,2,3]
print("x =",x)
print("e^x =",np.exp(x))
print("2^x =",np.exp2(x))
print("3^x =",np.power(3,x))
x = [1, 2, 3]
e^x = [ 2.71828183  7.3890561  20.08553692]
2^x = [2. 4. 8.]
3^x = [ 3  9 27]
1
2
3
4
5
x =  [1,2,4,10]
print("x = ",x)
print("ln(x) =",np.log(x))
print("log2(x) =",np.log2(x))
print("log10(x) = ",np.log10(x))
x =  [1, 2, 4, 10]
ln(x) = [0.         0.69314718 1.38629436 2.30258509]
log2(x) = [0.         1.         2.         3.32192809]
log10(x) =  [0.         0.30103    0.60205999 1.        ]

2.3.4 高级的通用函数特性

1.指定输出

1
2
3
4
x =np.arange(5)
y = np.empty(5)
np.multiply(x, 10, out = y)
print(y) #out用来指定计算结果存放位置
[ 0. 10. 20. 30. 40.]

也可以用作数组视图,例如可以将计算结果写入指定数组的每隔一个元素的位置

1
2
3
y = np.zeros(10)
np.power(2, x, out = y[::2])
print(y)
[ 1.  0.  2.  0.  4.  0.  8.  0. 16.  0.]

2.聚合

如果用特定的运算reduce一个数组。那么可以用任何通用函数的reduce方法。

1
2
x = np.arange(1,6)
np.add.reduce(x)#返回所有元素的和
15
1
np.multiply.reduce(x)#所有元素的成绩
120
1
np.add.accumulate(x)#需要存储每次计算的中间结果
array([ 1,  3,  6, 10, 15], dtype=int32)
1
np.multiply.accumulate(x)
array([  1,   2,   6,  24, 120], dtype=int32)

3.外积

1
2
x = np.arange(1,6)
np.multiply.outer(x,x) #获得两个不同输入数组所有元素对的函数运算结果
array([[ 1,  2,  3,  4,  5],
       [ 2,  4,  6,  8, 10],
       [ 3,  6,  9, 12, 15],
       [ 4,  8, 12, 16, 20],
       [ 5, 10, 15, 20, 25]])